/**
 * Copyright 2007 MartiniMix.net
 */
package net.martinimix.logging;

import java.util.ArrayList;
import java.util.List;

import com.bluemartini.dna.BMContext;
import com.bluemartini.dna.BMException;
import com.bluemartini.dna.BMLog;
import com.bluemartini.dna.Callback;
import com.bluemartini.dna.DNAList;

/**
 * Provides a startup call back to Intialize this Blue Martini 
 * Commons Logging implementation.
 * 
 * @author Scott Rossillo
 *
 */
public final class LogStartupCallback implements Callback {

	private static boolean initialized = false;
	
	private static final List logsToInitialize = new ArrayList(200);
	
	protected static void addLogForInitialization(BlueMartiniLog log) {
		
		if(log != null) {
			logsToInitialize.add(log);
		}
	}

	/**
	 * Returns true if the log system is initialized.
	 * 
	 * @return <code>true</code> if the log system is initialized;
	 * <code>false</code> otherwise
	 */
	public static boolean isInitialiazed() {
		return initialized;
	}

	/**
	 * Initializes logging system and any waiting loggers.
	 */
	public DNAList execute(DNAList in) throws BMException {
		
		Runtime.getRuntime().addShutdownHook(new LogShutdownHook());
		
		try {
			if(BlueMartiniLogFactory.DEBUG_INTERNAL_ENABLED) {
				System.err.println("Intializing BMLog ...");
			}
			BMLog.init();
			initialized = true;
			if(BlueMartiniLogFactory.DEBUG_INTERNAL_ENABLED) {
				System.err.println("Done initializing BMLog.");
			}
			
			synchronized(logsToInitialize) {
			
				if(BlueMartiniLogFactory.DEBUG_INTERNAL_ENABLED) {
					System.err.println("Intializing deferred logs ... " + logsToInitialize.size());
				}
				while(logsToInitialize.size() > 0) {
					( (BlueMartiniLog) logsToInitialize.remove(0) ).initLog();
				}
			}
			if(BlueMartiniLogFactory.DEBUG_INTERNAL_ENABLED) {
				System.err.println("Done initializing deferred logs.");
			}
			
		} catch (BMException e) {
			System.err.println("Failed to initialize BMLog: " + e.getMessage());
			throw new BMException("Failed to initialize BMLog: " + e.getMessage());
		}
		
		return null;
	}

	
	/**
	 * Provides a shutdown hook to store log messages waiting
	 * in log thread.
	 * 
	 * @author Scott Rossillo
	 *
	 */
	private static class LogShutdownHook extends Thread {
	    
		public LogShutdownHook() {
	        super();
	    }
	    
	    public void run() {
	    	
	        // hangout for 5.5 seconds to give the stupid log time to write data
	        try {
	        	boolean synchronous = 
	        		BMContext.getAppConfig().getList("log").getBoolean("synchronous", false);
	        	
	        	if(!synchronous) {
	        		Thread.sleep(5500L);
	        	}
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	    }
	}
}
